package org.swift.mashup.engine.jsr223;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptEngine;
import javax.script.ScriptException;

public class ScriptCache {
	private static final String KEY_LANG_DELIMITER = ">>>";

	public static ScriptCache getInstance() {
		return instance;
	}
	
	private static final int CACHE_SIZE = 30;
	private static final ScriptCache instance = new ScriptCache(CACHE_SIZE);
	
	private LinkedHashMap<String, CompiledScript> cacheMap;

	protected ScriptCache(final int maxCachedScripts) {
		cacheMap = new LinkedHashMap<String, CompiledScript>(maxCachedScripts, 1, true) {
			protected boolean removeEldestEntry(Map.Entry eldest) {
				return size() > maxCachedScripts;
			}
		};
	}

	synchronized public void clear() {
		cacheMap.clear();
	}
	
	synchronized public void clear(String language) {
		List<String> removekeys = new ArrayList<String>();
		
		for ( String key : cacheMap.keySet() ) {
			if ( key.startsWith(KEY_LANG_DELIMITER + language + KEY_LANG_DELIMITER) ) {
				removekeys.add(key);
			}
		}
		
		for ( String key : removekeys ) {
			cacheMap.remove(key);
		}
	}
	
	synchronized public CompiledScript getCompiledScript(String language, ScriptEngine engine, String source) 
		throws ScriptException {
		
		String key = createKey(language, source);
		CompiledScript compiledScript = cacheMap.get(key);
		
		if ( compiledScript == null ) {
			compiledScript = ((Compilable)engine).compile(source);
			cacheMap.put(key, compiledScript);
		}
		
		return compiledScript;
	}
	
	protected String createKey(String language, String source) {
		return KEY_LANG_DELIMITER + language + KEY_LANG_DELIMITER + source;
	}
	
	public static boolean supportsCompilation(ScriptEngine engine) {
		return (engine instanceof Compilable);
	}
}
